我們現在有了許多的基礎的 parser function 了,我們直接來看怎麼樣組合這些 function 來 parse 一些東西吧!以 library 裡面的 Android parser 為例,我們的目標是拿到 RSS 2.0 標準格式裡的 channel 資料。首先,我們先定義 channel 長的樣子包在一個 data class 裡面,而這個 data class 叫做 RssStandardChannelData ,完整的 data class 可以參考這個連結,這邊就不把完整程式碼貼上來了。Channel 裡面又有包含一些資料,我們就可以定義在另一個 data class 裡面,像是 category 、 item 和 cloud 等等。
接著,我們就可以來寫 channel 的 parser function 。
@Throws(IOException::class, XmlPullParserException::class)
private fun XmlPullParser.readRssStandardChannel(): RssStandardChannelData {
    require(XmlPullParser.START_TAG, null, CHANNEL)
		// 1
    var title: String? = null
    var image: Image? = null
    val categories = mutableListOf<Category>()
    var cloud: Cloud? = null
    var textInput: TextInput? = null
    var skipHours: List<Int>? = null
    val items = mutableListOf<RssStandardItemData>()
		// 省略其他變數宣告
		// 2
    while (next() != XmlPullParser.END_TAG) {
        if (eventType != XmlPullParser.START_TAG) continue
				// 3
        when (name) {
            TITLE -> title = readString(TITLE)
            IMAGE -> image = readImage()
            CATEGORY -> categories.add(readCategory())
            CLOUD -> cloud = readCloud()
            TTL -> ttl = readString(TTL)?.toIntOrNull()
            RATING -> rating = readString(RATING)
            TEXT_INPUT -> textInput = readTextInput()
            SKIP_HOURS -> skipHours = readSkipHours()
            ITEM -> items.add(readRssStandardItem())
						// 省略其他處理
            else -> skip()
        }
    }
    require(XmlPullParser.END_TAG, null, CHANNEL)
		// 4
    return RssStandardChannelData(...)
}
在這個 function 裡,我把他分成四個部分來講解,分別對應上方程式碼註解上的數字:
readString 之後再轉成想要的型別。如果 tag 還有另一個 tag ,可以再額外定義一個 data class 來代表該子 tag 。如果 tag 名稱不在處理的範圍,則可以呼叫 skip 去跳過該 tag 。在處理的過程中,有呼叫一些其他的 function ,像是 readCategory readTextInput readSkipHours 和 readRssStandardItem 等,它們內部處理的邏輯是和 readRssStandardChannel 相同,這些 function 可以在這邊找到。現在,我們掌握了使用原生的 XmlPullParser 的方法,可以組合出我們想要的資料 parser ,但別高興得太早!上一段程式碼是不是看起來有哪邊怪怪的?假設我們有很多種的資料型態和 tag 要取資料,那我們不就要每一種都寫一個 function 去處理?如果我們有方法可以去產生這些程式碼,我們不用自己手動寫。這個就是我們的 annotation processor 可以辦得到的事,下篇開始會講 annotation 和 annotation processor !